package com.buwei.module.rbac.domain.entity;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.FieldDefaults;

@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
@Entity
@EntityListeners(AuditingEntityListener.class)
@Table
public class Resource implements Serializable {

	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	Long id;
	
	/**
	 * 父节点的id
	 */
	Long pid;
	
	/**
	 * vue router路由名，需前端开发的页面相关知识（/users）
	 * 
	 */
	@Column(length=64)
	String path;
	
	/**
	 * 组件名称，需前端开发的页面相关知识（Users）
	 */
	@Column(length=64)
	String component;
	
	/**
	 * 组件存放路径，需前端开发的页面相关知识（common/UserInfo, common/UserIndex, GmtonltranList）
	 */
	@Column(length=64)
	String componentPath;
	
	@Column(length=20)
	String name;
	
	@Column(length=128)
	String description;
	
	/**
	 * 页面显示的从上至下排序列
	 */
	Integer sort;
	
	/**
	 * 文本前显示的图标(fa fa-bar-chart fa-lg)
	 */
	@Column(length=64)
	String icon;
	
	/**
	 * 是否是导航菜单的路由记录
	 */
	Boolean isMenu;
	
	/**
	 * 是否可以进行路由
	 * 如果Menu父节点el-submenu，不能进行路由，只能展开: 
	 * 如果是Menu子节点el-menu-item和页面节点，可以进行路由
	 */
	Boolean canRoute;
	
	/**
	 * 完整的面包屑路径（0,1,2,）
	 */
//	@Column(length=20)
//	String breadcrumbPath;
	
	/**
	 * json配置子项
	 * {
	 * 	test:'mind-edit',
	 * 	add:true,
	 * 	update:false
	 * }
	 */
	String extra;
	
	/*
	 * jackson中的@JsonBackReference和@JsonManagedReference，
	 * 以及@JsonIgnore均是为了解决对象中存在双向引用导致的无限递归（infinite recursion）问题。
	 * 这些标注均可用在属性或对应的get、set方法中。 
	 * @JsonBackReference和@JsonManagedReference：这两个标注通常配对使用，通常用在父子关系中。
	 * @JsonBackReference标注的属性在序列化（serialization，即将对象转换为json数据）时，会被忽略（即结果中的json数据不包含该属性的内容）。
	 * @JsonManagedReference标注的属性则会被序列化。在序列化时，@JsonBackReference的作用相当于@JsonIgnore，此时可以没有@JsonManagedReference。
	 * 但在反序列化（deserialization，即json数据转换为对象）时，如果没有@JsonManagedReference，则不会自动注入@JsonBackReference标注的属性（被忽略的父或子）
	 * ；如果有@JsonManagedReference，则会自动注入自动注入@JsonBackReference标注的属性。 
	 * @JsonIgnore：直接忽略某个属性，以断开无限递归，序列化或反序列化均忽略。当然如果标注在get、set方法中，则可以分开控制，序列化对应的是get方法，
	 * 反序列化对应的是set方法。在父子关系中，当反序列化时，@JsonIgnore不会自动注入被忽略的属性值（父或子），
	 * 这是它跟@JsonBackReference和@JsonManagedReference最大的区别。 
	 */
	// mappedBy相等于inverse,如果不加这一句，会多生成一个中间表
	/*
	@JsonIgnore
	@Transient
	@ManyToMany(cascade = { CascadeType.ALL }, 
			mappedBy = "resources", // 通过维护端的属性关联
			targetEntity = Role.class, 
			fetch = FetchType.LAZY)
	List<Role> roles;
	*/
	
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+08:00")
	@CreatedDate
    LocalDateTime createdAt;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+08:00")
    @LastModifiedDate
    LocalDateTime editedAt;
    
    /**
     * @Description : 创建登录后的首页路由节点
     * ---------------------------------
     * @Author : Bu Wei
     * @Date : Created at 2018年1月18日 上午9:40:22
     */
    public static Resource createIndexRouteNode(String component, String componentPath){
    	Resource indexRouteNode = new Resource();
    	indexRouteNode.setPid(0L);
    	indexRouteNode.setPath("/");
    	indexRouteNode.setComponent(component);
    	indexRouteNode.setComponentPath(componentPath);
    	indexRouteNode.setName("首页");
    	indexRouteNode.setDescription("首页");
    	indexRouteNode.setIsMenu(false);
    	indexRouteNode.setCanRoute(true);
    	indexRouteNode.setIcon("");
    	indexRouteNode.setExtra("");
		return indexRouteNode;
    }
    
    /**
     * @Description : 
     * 创建非叶子节点，
     * 非叶子节点的父节点pid为0（首页）；
     * 非叶子节点的webPath为空，因为不需要点击，只有展开子菜单操作；
     * ---------------------------------
     * @Author : Bu Wei
     * @Date : Created at 2018年1月12日 下午4:53:55
     */
    public static Resource createMenuNotLeafNode(Long pid, String name, String icon, Integer sort, String extra){
    	Resource menuNotLeafNode = new Resource();
    	menuNotLeafNode.setPid(pid);
    	menuNotLeafNode.setPath("");
    	menuNotLeafNode.setName(name);
    	menuNotLeafNode.setDescription(name);
    	menuNotLeafNode.setIsMenu(true);
    	menuNotLeafNode.setCanRoute(false);
    	menuNotLeafNode.setIcon(icon);
    	menuNotLeafNode.setSort(sort);
    	menuNotLeafNode.setExtra(extra);
		return menuNotLeafNode;
    }
    
    /**
     * @Description : 
     * 创建叶子节点，
     * 叶子节点 必须指定父节点pid；
     * 叶子节点 必须指定父节点webPath；
     * ---------------------------------
     * @Author : Bu Wei
     * @Date : Created at 2018年1月12日 下午4:53:55
     */
    public static Resource createMenuLeafNode(Long pid, String path, String component, String componentPath, String name, Integer sort,  String extra){
    	Resource menuLeafNode = new Resource();
    	menuLeafNode.setPid(pid);
    	menuLeafNode.setPath(path);
    	menuLeafNode.setComponent(component);
    	menuLeafNode.setComponentPath(componentPath);
    	menuLeafNode.setName(name);
    	menuLeafNode.setDescription(name);
    	menuLeafNode.setIsMenu(true);
    	menuLeafNode.setCanRoute(true);
    	menuLeafNode.setIcon("");
    	menuLeafNode.setSort(sort);
    	menuLeafNode.setExtra(extra);
		return menuLeafNode;
    }
    
    /**
     * 
     * @Description : 创建非侧边栏导航菜单的可路由节点
     * ---------------------------------
     * @Author : Bu Wei
     * @Date : Created at 2018年1月18日 上午9:38:53
     */
    public static Resource createNotMenuCanRouteNode(Long pid, String path, String component, String componentPath, String name, String extra){
    	Resource menuLeafNode = new Resource();
    	menuLeafNode.setPid(pid);
    	menuLeafNode.setPath(path);
    	menuLeafNode.setComponent(component);
    	menuLeafNode.setComponentPath(componentPath);
    	menuLeafNode.setName(name);
    	menuLeafNode.setDescription(name);
    	menuLeafNode.setIsMenu(false);
    	menuLeafNode.setCanRoute(true);
    	menuLeafNode.setIcon("");
    	menuLeafNode.setExtra(extra);
		return menuLeafNode;
    }
    
    



	
}
